]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
st/icon: Automatically update on icon theme changes
authorFlorian Müllner <fmuellner@gnome.org>
Tue, 23 Jan 2024 20:20:51 +0000 (21:20 +0100)
committerMarge Bot <marge-bot@gnome.org>
Fri, 26 Jan 2024 23:36:25 +0000 (23:36 +0000)
St.Icon is very commonly used for displaying themed icons, yet so
far updating the icon on icon theme changes is left to the caller.

Unsurprisingly, very few actually do that, with the result that
for most icons, icon theme changes only take effect after a delay
(say, a color change on hover) or not at all.

This is also inconsistent with GTK, where Gtk.Image will automatically
pick up icon theme changes.

Address this by tracking whether the current icon corresponds to
a themed icon, and update it automatically on theme changes if
it does.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3141>

src/st/st-icon.c

index 6a32df5b38e5ef4a1ad4264cc437e2b0cbf0dfd5..c9e29ee3f01a9ecef05974292efa3cab169df943 100644 (file)
@@ -53,6 +53,7 @@ struct _StIconPrivate
   ClutterActor    *icon_texture;
   ClutterActor    *pending_texture;
   gulong           opacity_handler_id;
+  gulong           icon_theme_changed_id;
 
   GIcon           *gicon;
   gint             prop_icon_size;  /* icon size set as property */
@@ -60,6 +61,7 @@ struct _StIconPrivate
   gint             icon_size;       /* icon size we are using */
   GIcon           *fallback_gicon;
   gboolean         needs_update;
+  gboolean         is_themed;
 
   StIconColors     *colors;
 
@@ -80,6 +82,13 @@ static GIcon *default_gicon = NULL;
 #define IMAGE_MISSING_ICON_NAME "image-missing"
 #define DEFAULT_ICON_SIZE 48
 
+static void
+on_icon_theme_changed (StIcon *icon)
+{
+  if (icon->priv->is_themed)
+    st_icon_update (icon);
+}
+
 static void
 st_icon_set_property (GObject      *gobject,
                       guint         prop_id,
@@ -170,6 +179,9 @@ st_icon_dispose (GObject *gobject)
       priv->pending_texture = NULL;
     }
 
+  g_clear_signal_handler (&priv->icon_theme_changed_id,
+                          st_texture_cache_get_default ());
+
   g_clear_object (&priv->gicon);
   g_clear_object (&priv->fallback_gicon);
   g_clear_pointer (&priv->colors, st_icon_colors_unref);
@@ -354,6 +366,7 @@ static void
 st_icon_init (StIcon *self)
 {
   ClutterLayoutManager *layout_manager;
+  StTextureCache *texture_cache;
 
   if (G_UNLIKELY (default_gicon == NULL))
     default_gicon = g_themed_icon_new (IMAGE_MISSING_ICON_NAME);
@@ -363,6 +376,11 @@ st_icon_init (StIcon *self)
   layout_manager = clutter_bin_layout_new ();
   clutter_actor_set_layout_manager (CLUTTER_ACTOR (self), layout_manager);
 
+  texture_cache = st_texture_cache_get_default ();
+  self->priv->icon_theme_changed_id =
+    g_signal_connect_swapped (texture_cache, "icon-theme-changed",
+                              G_CALLBACK (on_icon_theme_changed), self);
+
   /* Set the icon size to -1 here to make sure we apply the scale to the
    * default size on the first "style-changed" signal. */
   self->priv->icon_size = -1;
@@ -462,6 +480,32 @@ opacity_changed_cb (GObject *object,
   st_icon_finish_update (icon);
 }
 
+static ClutterActor *
+load_gicon (StTextureCache *cache,
+            StThemeNode    *theme_node,
+            GIcon          *gicon,
+            int             size,
+            int             paint_scale,
+            float           resource_scale,
+            gboolean       *is_themed)
+{
+  ClutterActor *texture;
+
+  g_assert (is_themed != NULL);
+
+  texture = st_texture_cache_load_gicon (cache,
+                                         theme_node,
+                                         gicon,
+                                         size,
+                                         paint_scale,
+                                         resource_scale);
+
+
+  if (texture)
+    *is_themed = G_IS_THEMED_ICON (gicon);
+  return texture;
+}
+
 static void
 st_icon_update (StIcon *icon)
 {
@@ -504,29 +548,34 @@ st_icon_update (StIcon *icon)
 
   cache = st_texture_cache_get_default ();
 
+  priv->is_themed = FALSE;
+
   if (priv->gicon != NULL)
-    priv->pending_texture = st_texture_cache_load_gicon (cache,
-                                                         theme_node,
-                                                         priv->gicon,
-                                                         priv->icon_size / paint_scale,
-                                                         paint_scale,
-                                                         resource_scale);
+    priv->pending_texture = load_gicon (cache,
+                                        theme_node,
+                                        priv->gicon,
+                                        priv->icon_size / paint_scale,
+                                        paint_scale,
+                                        resource_scale,
+                                        &priv->is_themed);
 
   if (priv->pending_texture == NULL && priv->fallback_gicon != NULL)
-    priv->pending_texture = st_texture_cache_load_gicon (cache,
-                                                         theme_node,
-                                                         priv->fallback_gicon,
-                                                         priv->icon_size / paint_scale,
-                                                         paint_scale,
-                                                         resource_scale);
+    priv->pending_texture = load_gicon (cache,
+                                        theme_node,
+                                        priv->fallback_gicon,
+                                        priv->icon_size / paint_scale,
+                                        paint_scale,
+                                        resource_scale,
+                                        &priv->is_themed);
 
   if (priv->pending_texture == NULL)
-    priv->pending_texture = st_texture_cache_load_gicon (cache,
-                                                         theme_node,
-                                                         default_gicon,
-                                                         priv->icon_size / paint_scale,
-                                                         paint_scale,
-                                                         resource_scale);
+    priv->pending_texture = load_gicon (cache,
+                                        theme_node,
+                                        default_gicon,
+                                        priv->icon_size / paint_scale,
+                                        paint_scale,
+                                        resource_scale,
+                                        &priv->is_themed);
   priv->needs_update = FALSE;
 
   if (priv->pending_texture)